﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace GomokuCommon {
    // 游戏结束原因
    public enum GameOverReason {
        LOST,           // 失败
        RIVAL_ADMIT,    // 对手认输
        SELF_ADMIT,     // 自己认输
        WON             // 胜利
    }

    // 协议
    [Serializable]
    public class GomokuProtocol {
        public const string SERVER_IP = "192.168.1.112";    // 服务器 IP 地址
        public const int SERVER_PORT = 10000;               // 服务器端口号

        public enum Type {
            FIND_USERS,     // 寻找其它用户
            GAME_OVER,      // 游戏结束
            INVITE_REQUEST, // 挑战请求
            INVITE_RESULT,  // 挑战结果
            LOGON,          // 登录
            PUT_PIECE,      // 放置棋子
            QUIT_GAME       // 退出游戏
        }

        public Type mType;          // 类型
        public string mUsername;    // 用户名

        /**
         * 构造方法。
         * @param type      类型
         * @param username  用户名
         */
        public GomokuProtocol(Type type, string username) {
            mType = type;
            mUsername = username;
        }

        /**
         * 将字节数组转换为协议。
         * @param bytes 字节数组 
         */
        public static GomokuProtocol FromBytes(byte[] bytes) {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream(bytes);
            stream.Seek(0, SeekOrigin.Begin);
            return (GomokuProtocol)formatter.Deserialize(stream);
        }

        /**
         * 将协议转换为字节数组。
         * @param obj   协议
         */
        public static byte[] ToBytes(object obj) {
            BinaryFormatter formmatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formmatter.Serialize(stream, obj);
            return stream.GetBuffer();
        }
    }
    
    // 寻找用户请求
    [Serializable]
    public class FindUsersRequest: GomokuProtocol {
        /**
         * 构造方法。
         * @param username  用户名
         */
        public FindUsersRequest(string username): 
            base(Type.FIND_USERS, username) {
        }
    }

    // 寻找用户结果
    [Serializable]
    public class FindUsersResult: GomokuProtocol {
        public List<string> mUsernameList;  // 用户名列表

        /**
         * 构造方法。
         * @param usernameList  用户名列表
         */
        public FindUsersResult(List<string> usernameList): 
            base(Type.FIND_USERS, "") {
            mUsernameList = usernameList;
        }
    }

    // 游戏结束
    [Serializable]
    public class GameOver: GomokuProtocol {
        public GameOverReason mReason;  // 结束原因

        /**
         * 构造方法。
         * @param reason    结束原因
         * @param rivalName 对手的名字
         */
        public GameOver(GameOverReason reason, string rivalName): 
            base(Type.GAME_OVER, rivalName) {
            mReason = reason;
        }
    }

    // 挑战请求
    [Serializable]
    public class InviteRequest: GomokuProtocol {
        public string mRivalName;   // 对手的名字

        /**
         * 构造方法。
         * @param rivalName 对手的名字
         * @param username  用户名
         */
        public InviteRequest(string rivalName, string username): 
            base(Type.INVITE_REQUEST, username) {
            mRivalName = rivalName;
        }
    }

    // 挑战结果
    [Serializable]
    public class InviteResult: GomokuProtocol {
        public bool mAccept;        // 接受挑战则为 true，否则为 false
        public string mRivalName;   // 对手的名字

        /**
         * 构造方法。
         * @param accept    接受挑战则为 true，否则为 false
         * @param rivalName 对手的名字
         * @param username  用户名
         */
        public InviteResult(bool accept, string rivalName, string username): 
            base(Type.INVITE_RESULT, username) {
            mAccept = accept;
            mRivalName = rivalName;
        }
    }

    // 登录请求
    [Serializable]
    public class LogonRequest: GomokuProtocol {
        /**
         * 构造方法。
         * @param username  用户名
         */
        public LogonRequest(string username) :
            base(Type.LOGON, username) {
        }
    }

    // 登录结果
    [Serializable]
    public class LogonResult: GomokuProtocol {
        /**
         * 构造方法。
         * @param username  用户名
         */
        public LogonResult(string username) :
            base(Type.LOGON, username) {
        }
    }

    // 放置棋子
    [Serializable]
    public class PutPiece: GomokuProtocol {
        public int mX;  // x 坐标（窗口坐标）
        public int mY;  // y 坐标（窗口坐标）

        /**
         * 构造方法。
         * @param rivalName 对手的名字
         * @param x, y      棋子位置（窗口坐标）
         */
        public PutPiece(string rivalName, int x, int y): 
            base(Type.PUT_PIECE, rivalName) {
            mX = x;
            mY = y;
        }
    }

    // 退出游戏
    [Serializable]
    public class QuitGame: GomokuProtocol {
        /**
         * 构造方法。
         * @param username  用户名
         */
        public QuitGame(string username): 
            base(Type.QUIT_GAME, username) {
        }
    }
}
